package com.zmj.utils;

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnel;
import com.google.common.hash.Funnels;

/**
 * @author zmj
 * @date 2021-09-16 09:00
 * <p>
 * 布隆过滤器
 * <p>
 * 命中-> 不一定存在（误判取决于数组长度和hash算法）
 * 未命中-> 肯定不存在
 */
public class BloomFilterUtil {

    /**
     * 预计要插入数据数量
     */
    private static int size = 1000000;

    /**
     * 期望的误判率
     */
    private static double fpp = 0.0001;


    /**
     * 创建自定义默认布隆过滤器
     *
     * @param funnel 预计插入多少数据
     * @param size   预计要插入数据数量
     * @param fpp    期望的误判率
     * @param <T>
     * @return
     */
    public static <T> BloomFilter<T> getCustomBloomFilter(Funnel<? super T> funnel, int size, double fpp) {
        return BloomFilter.create(funnel, size, fpp);
    }

    /**
     * 生成默认布隆过滤器
     *
     * @return
     */
    public static BloomFilter<Integer> getBloomFilter() {
        return getCustomBloomFilter(Funnels.integerFunnel(), size, fpp);
    }

    public static void main(String[] args) {
        guavaTest();
    }


    public static void guavaTest() {
        BloomFilter<Integer> bloomFilter = getBloomFilter();

        // 模拟插入10万样本数据【0-99999】
        for (int i = 0; i < size; i++) {
            bloomFilter.put(i);
        }

        // 用另外十万测试数据，测试存在的误判率 测试数据为【100000-199999】
        int count = 0;
        for (int i = size; i < size + 100000; i++) {
            if (bloomFilter.mightContain(i)) {
                count++;
                System.out.println(i + "误判了");
            }
        }
        System.out.println("总共的误判数:" + count);
    }

}
